import {_decorator, Component, director, instantiate, Node, Prefab, resources, SpriteFrame} from "cc";
import {userInfo} from "db://assets/script/user-info";
import {GameEvent} from "db://assets/script/game-event";
import {
    FishAttackRecordReply,
    FishBattleCompleteReply,
    FishDeadReply,
    FishExploreReply,
    FishPreAttackReply
} from "db://assets/proto/new-world-ws/v1/internal";
import {propsConfigsLoader} from "db://assets/script/configs/props-configs-loader";
import {MessageItem} from "db://assets/script/game/mainui/city/message-item";
import {MessageType} from "db://assets/script/game/constants/message";
import {serverTimeHelper} from "db://assets/script/server-time-helper";
import {BuildingItem} from "db://assets/proto/new-world-api/v1/building";
import {buildingConfigsLoader} from "db://assets/script/configs/building-configs-loader";
import {configsHelper} from "db://assets/script/configs-helper";

const {ccclass, property} = _decorator;

@ccclass('MessageBox')
export class MessageBox extends Component {

    maxNum: number = 5

    @property(Prefab)
    messageItemPrefab!: Prefab

    msgItems: Array<Node> = []

    inBattleCache: Map<string, number> = new Map()

    start() {
        this.onEvent()
    }

    onEvent() {
        director.on(GameEvent.fishBeginBattle, this._onBeginBattle, this)
        director.on(GameEvent.fishInBattle, this._onInAttack, this)
        director.on(GameEvent.fishBeginDead, this._onFishDead, this)
        director.on(GameEvent.fishBeginExplore, this._onFishExplore, this)
        director.on(GameEvent.fishBattleComplete, this._onCompleteBattle, this)
        director.on(GameEvent.userFishFrySee, this._onFishFrySee, this)
        director.on(GameEvent.userFishFryNewCome, this._onFishFryNewCome, this)
        director.on(GameEvent.cityBuildingUpgradeComplete, this._onUpgradeComplete, this)
        director.on(GameEvent.cityBuildingRemoveComplete, this._onRemoveComplete, this)
    }

    offEvent() {
        director.off(GameEvent.fishBeginBattle, this._onBeginBattle, this)
        director.off(GameEvent.fishInBattle, this._onInAttack, this)
        director.off(GameEvent.fishBeginDead, this._onFishDead, this)
        director.off(GameEvent.fishBeginExplore, this._onFishExplore, this)
        director.off(GameEvent.fishBattleComplete, this._onCompleteBattle, this)
        director.off(GameEvent.userFishFrySee, this._onFishFrySee, this)
        director.off(GameEvent.userFishFryNewCome, this._onFishFryNewCome, this)
        director.off(GameEvent.cityBuildingUpgradeComplete, this._onUpgradeComplete, this)
        director.off(GameEvent.cityBuildingRemoveComplete, this._onRemoveComplete, this)
    }


    private _onRemoveComplete(event: BuildingItem) {
        let msgText = ''
        const bc = configsHelper.loadBuildingConfig(event.buildingId)
        const pc = propsConfigsLoader.findPropConfigs(bc.propId.toNumber())
        msgText = '「' + pc!.name + '」拆除完毕！'
        this.initItem(MessageType.BuildingBuildComplete, msgText, new Map(
            [
                ['buildingId', event.buildingId.toString()]
            ]
        ))
        return;
    }

    private _onUpgradeComplete(event: BuildingItem) {
        let msgText = ''
        const bc = configsHelper.loadBuildingConfig(event.buildingId)
        const pc = propsConfigsLoader.findPropConfigs(bc.propId.toNumber())
        if (event.level == 1) {
            msgText = '「' + pc!.name + '」建造完成！'
            this.initItem(MessageType.BuildingBuildComplete, msgText, new Map(
                [
                    ['buildingId', event.buildingId.toString()]
                ]
            ))
            return;
        } else {
            msgText = '「' + pc!.name + '」升级完成！'
            this.initItem(MessageType.BuildingUpgradeComplete, msgText, new Map(
                [
                    ['buildingId', event.buildingId.toString()]
                ]
            ))
            return;
        }
    }

    private _onBeginBattle(event: FishPreAttackReply) {
        const uid = userInfo.loadUid()
        const attacker = userInfo.fishInfo.loadFishById(event.attacker)
        const defender = userInfo.fishInfo.loadFishById(event.defender)
        let msgText = ''
        if (attacker?.masterInfo?.masterId == uid) {
            msgText = '「' + attacker.baseInfo!.fishName + '」开始战斗！'
            this.inBattleCache.set(attacker.id.toString(), serverTimeHelper.loadServerTime())
        }
        if (defender?.masterInfo?.masterId == uid) {
            msgText = '「' + defender.baseInfo!.fishName + '」开始战斗！'
            this.inBattleCache.set(defender.id.toString(), serverTimeHelper.loadServerTime())
        }
        if (msgText == '') return
        this.initItem(MessageType.BeginBattle, msgText, new Map())
    }


    private _onInAttack(event: FishAttackRecordReply) {
        const uid = userInfo.loadUid()
        const attacker = userInfo.fishInfo.loadFishById(event.attackId)
        const defender = userInfo.fishInfo.loadFishById(event.defenceId)
        let msgText = ''
        if (attacker?.masterInfo?.masterId == uid) {
            const latestShow = this.inBattleCache.get(attacker.id.toString()) || -1
            const nowMs = serverTimeHelper.loadServerTime()
            if (nowMs != -1 && (nowMs - latestShow) <= 3 * 60 * 1000) {
                return;
            }
            this.inBattleCache.set(attacker.id.toString(), nowMs)
            msgText = '「' + attacker.baseInfo!.fishName + '」开始战斗！'
        }
        if (defender?.masterInfo?.masterId == uid) {
            const latestShow = this.inBattleCache.get(defender.id.toString()) || -1
            const nowMs = serverTimeHelper.loadServerTime()
            if (nowMs != -1 && (nowMs - latestShow) <= 3 * 60 * 1000) {
                return;
            }
            this.inBattleCache.set(defender.id.toString(), nowMs)
            msgText = '「' + defender.baseInfo!.fishName + '」开始战斗！'
        }
        if (msgText == '') return
        this.initItem(MessageType.BeginBattle, msgText, new Map())
    }


    private _onFishDead(event: FishDeadReply) {
        const uid = userInfo.loadUid()
        const fish = userInfo.fishInfo.loadFishById(event.fishId)
        let msgText = ''
        if (fish?.masterInfo?.masterId == uid) {
            msgText = '「' + fish.baseInfo!.fishName + '」战败！'
        }
        if (msgText == '') return
        this.initItem(MessageType.Death, msgText, new Map())
    }

    private _onFishExplore(event: FishExploreReply) {
        const uid = userInfo.loadUid()
        const fish = userInfo.fishInfo.loadFishById(event.fishId)
        if (fish?.masterInfo?.masterId == uid) {
            event.prop.forEach((num, propId) => {
                const pc = propsConfigsLoader.findPropConfigs(propId.toNumber())
                const msgText = '「' + fish.baseInfo!.fishName + '」探得宝物: ' + pc!.name + 'x' + num.toString()
                this.initItem(MessageType.Explore, msgText, new Map(
                    [
                        ['propId', propId.toString()]
                    ]
                ))
            })

        }
    }

    private _onCompleteBattle(event: FishBattleCompleteReply) {
        const uid = userInfo.loadUid()
        const fish = userInfo.fishInfo.loadFishById(event.fishId)
        let msgText = ''
        if (fish?.masterInfo?.masterId == uid) {
            msgText = '「' + fish.baseInfo!.fishName + '」战斗结束。'
        }
        if (msgText == '') return
        this.initItem(MessageType.BattleComplete, msgText, new Map())
    }

    private _onFishFryNewCome() {
        this.initItem(MessageType.FishFryCome, '有新弟子登门拜师！', new Map())
    }

    private _onFishFrySee() {
        const tmp: Array<Node> = []
        this.msgItems.forEach((item) => {
            if (item.getComponent(MessageItem)!.messageType == MessageType.FishFryCome) {
                item.destroy()
            } else {
                tmp.push(item)
            }
        })
        this.msgItems = tmp
    }

    private initItem(messageType: MessageType, message: string, extra: Map<string, string>): void {
        const itemNode = instantiate(this.messageItemPrefab)
        const item = itemNode.getComponent(MessageItem)!
        if (messageType == MessageType.FishFryCome) {
            item.initFixed(messageType, message, extra)
        } else if (messageType == MessageType.BuildingBuildComplete || messageType == MessageType.BuildingUpgradeComplete || messageType == MessageType.BuildingRemoveComplete) {
            const nowMs = serverTimeHelper.loadServerTime()
            item.initTimedFixed(messageType, message, nowMs + 10000, extra)
        } else {
            item.initNotFixed(messageType, message, extra)
        }
        this.msgItems.push(itemNode)
        this.node.addChild(itemNode)
        if (this.msgItems.length > this.maxNum) {
            const tmp: Array<Node> = []
            while (true) {
                const n = this.msgItems.shift()
                if (!n) break
                if (n.getComponent(MessageItem)!.checkFixed()) {
                    tmp.push(n)
                    continue
                }
                n.destroy()
                break
            }
            if (tmp.length > 0) {
                this.msgItems.push(...tmp)
            }
        }
    }

    protected onDestroy(): void {
        this.offEvent()
    }
}